package com.kaifamiao.collection;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;

/**
 * 实现 Collection 接口中的核心功能，并用数组实现元素的存储
 * @param <X> 类型参数 X 表示 Container 中存放元素类型 (对于 Container类 来说 X 属于形参)
 *            对于 `implements Collection<X>` 中的 `X` 相当于是 Collection 类型参数的 实参
 */
public class Container<X> implements Collection<X> {

    // 约定默认初始容量为 10
    private static final int DEFAULT_INITIAL_CAPACITY = 10;
    // 约定默认加载因子
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    // 定义一个实例变量用来记录存储数据的数组
    private Object[] elements;
    // 用来记录元素个数的实例变量
    private int count;
    // 用来记录加载因子的实例变量
    private float factor;

    // Collection接口中所要求的"标准"构造方法: 无参数构造
    public Container(){
        elements = new Object[ DEFAULT_INITIAL_CAPACITY ];
        factor = DEFAULT_LOAD_FACTOR;
    }

    // Collection接口中所要求的"标准"构造方法: 带有Collection参数的构造
    public Container( Collection<X> c ){
        this();
        this.addAll( c );
    }

    @Override
    public boolean add( X e ) {
        ensureCapacity();
        elements[ count++ ] = e;
        return true;
    }

    private void ensureCapacity(){
        // 判断是否到达扩容条件
        if( count >= elements.length * factor ) {
            // 先将原数组用临时变量缓存起来
            Object[] temp = elements;
            // oldCapacity * 3 / 2 + 1
            elements = new Object[ temp.length * 3 / 2 + 1 ];
            // 把原数组中 [0, count) 之间的元素拷贝到新数组中
            System.arraycopy(temp,0,elements,0,count);
        }
    }

    @Override
    public int size() {
        return count;
    }

    @Override
    public boolean isEmpty() {
        return count == 0 ;
    }

    @Override
    public void clear() {
        Arrays.fill(elements, 0, count, null );
        count = 0;
    }

    @Override
    public Object[] toArray() {
        return Arrays.copyOfRange(elements,0,count);
    }

    @Override
    public boolean contains(Object e) {
        X s = (X) e ;
        return indexOf( s ) != -1 ;
    }

    // 不属于Collection接口中的方法
    public int indexOf( X e ){
        for (int i = 0; i < count; i++) {
            Object x = elements[i];
            if( Objects.equals( x , e ) ) {
                return i;
            }
        }
        return -1;
    }

    // 不属于Collection接口中的方法
    public int lastIndexOf( X e ){
        for (int i = count -1 ; i >= 0; i--) {
            Object x = elements[i];
            if( Objects.equals( x , e ) ) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public boolean remove(Object o) {
        int index = indexOf( (X)o );
        if( index != -1 ) {
            int n = count - 1 - index;
            System.arraycopy(elements,index+1,elements,index,n);
            elements[--count] = null;
            return true;
        }
        return false;
    }

    @Override
    public boolean addAll( Collection<? extends X> c ) {
        // 仅考虑 Container 类型，暂时不考虑其它类型
        if( c instanceof Container ) {
            Container<X> con = (Container<X>)c;
            for( int i = 0; i < con.count; i++ ){
                X e = (X)con.elements[i];
                // 调用 当前实例(this) 的 add 方法 将 元素 e 添加到 集合中
                this.add( e );
            }
            return true;
        }

        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append( "[" );
        for (int i = 0; i < count ; i++) {
            Object e = elements[i];
            builder.append( e );
            builder.append( ',' );
        }
        int last = builder.lastIndexOf(",");
        if( last != -1 ) {
            builder.deleteCharAt( last );
        }
        builder.append( "]" );
        String str = builder.toString();
        return str;
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public Iterator<X> iterator() {
        return null;
    }
}
